package com.its.common.net.server.channel;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Singleton;
import com.its.common.net.core.dto.GenericNetDTO;
import com.its.common.net.core.util.ChannelUtil;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelId;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.AttributeKey;
import io.netty.util.concurrent.GlobalEventExecutor;
import lombok.extern.slf4j.Slf4j;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @Author xiaxp
 * @Date 9/1/22 17:17
 * @Description
 */
@Slf4j
public class DefaultChannelManager implements ChannelManager {

    private ChannelGroup channels;

    private DefaultChannelManager() {
        channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
    }

    public static ChannelManager getInstance() {
        return Singleton.get(DefaultChannelManager.class);
    }

    @Override
    public void addChannel(Channel channel) {
        Assert.notNull(channel, "channel不能为空");
        channels.add(channel);
    }

    @Override
    public void removeChannel(ChannelId channelId) {
        Assert.notNull(channelId, "channelId不能为空");
        channels.remove(channelId);
        Channel channel = channels.find(channelId);
        if(null != channel){
            final String addrRemote = ChannelUtil.extractRemoteAddr(channel);
            channel.close().addListener((ChannelFutureListener) future ->
                    log.info("关闭Channel: 远程地址[{}] 结果: {}", addrRemote,
                    future.isSuccess()));
        }
    }

    @Override
    public List<Channel> getAllChannels() {
        if (channels.isEmpty()) {
            return Collections.emptyList();
        }
        return channels.stream().collect(Collectors.toList());
    }

    @Override
    public ChannelWrapper getChannelWrapper(ChannelId channelId) {
        Assert.notNull(channelId, "channelId不能为空");
        if (channels.isEmpty()) {
            return null;
        }
        Channel channel = channels.find(channelId);
        return wrapChannel(channel);
    }

    @Override
    public ChannelWrapper getChannelWrapper(String longId) {
        Assert.notNull(longId, "channelId不能为空");
        if (channels.isEmpty()) {
            return null;
        }
        Channel channel = channels.stream()
                .filter(item -> item.id().asLongText().equals(longId))
                .findFirst()
                .orElse(null);
        return wrapChannel(channel);
    }

    @Override
    public List<ChannelWrapper> getAllChannelWrappers() {
        if (channels.isEmpty()) {
            return Collections.emptyList();
        }
        return channels.stream()
                .map(this::wrapChannel)
                .collect(Collectors.toList());
    }
    @Override
    public Channel getChannelFromChannelId(ChannelId channelId){
        Assert.notNull(channelId, "channelId不能为空");
        return channels.find(channelId);
    }
    @Override
    public Channel getChannelFromAddrAndPort(String addr, int port){
        Channel channel = channels.stream().filter(ch -> {
            GenericNetDTO.Sender sender = ChannelUtil.extractRemoteInfo(ch);
            if(Objects.equals(sender.address, addr) && port == sender.port){
                return true;
            }
            return false;
        }).findFirst().get();
        return channel;
    }

    public Optional<Channel> filterByAttribute(AttributeKey key, String attr) {
        List<Channel> all = getAllChannels();
        return all.stream().filter(channel -> channel.attr(key).equals(attr)).findFirst();
    }

    private ChannelWrapper wrapChannel(Channel channel) {
        return channel == null ? null : ChannelWrapper.builder()
                .channel(channel)
                .build();
    }
}
